//
//  NSArrayBlocksViewController.m
//  BlocksKitLearn
//
//  Created by Elvis on 2017/8/18.
//  Copyright © 2017年 Elvis. All rights reserved.
//

#import "NSArrayBlocksViewController.h"

static NSString *identifier = @"UITableViewCell";

@interface NSArrayBlocksViewController ()<UITableViewDelegate, UITableViewDataSource>

@property (strong, nonatomic) NSArray *itemArray;

@property (strong, nonatomic) UITextView *textView;

@property (strong, nonatomic) UITableView *tableView;

@property (copy, nonatomic) NSArray *methods;

@end

@implementation NSArrayBlocksViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.textView];
    [self.view addSubview:self.tableView];
}

/**
 * 简单遍历,可实现对内部成员进项某项操作,相当于 [array makeObjectsPerformSelector:@selelctor(foo)];
 */
- (void)each{
    NSMutableString *text = [NSMutableString string];
    [self.itemArray bk_each:^(id obj) {
        NSLog(@"obj = %@",obj);
        [text appendFormat:@"obj = %@\n",obj];
    }];
    
    self.textView.text = text;
}

/**
 * 多核遍历,使用的是enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block;内部应使用 GCD 的 group, 在 background queue 遍历,但需要注意线程安全问题
 */
- (void)apply{
    NSMutableString *text = [NSMutableString string];
    [self.itemArray bk_apply:^(id obj) {
        NSLog(@"obj = %@",obj);
        @synchronized (text) {
            [text appendFormat:@"obj = %@\n",obj];
        }
    }];
    
    self.textView.text = text;
}

/**
 * 根据条件用来获取一个NSUIndex 对象，主要是根据条件进行数据遍历使用,只会返回第一个找到的匹配对象
 */
- (void)match{
    
    id obj = [self.itemArray bk_match:^BOOL(NSString *obj) {
        return [obj isEqualToString:@"Marion-Italic"];
    }];
    
    NSLog(@"obj %@",obj);
    self.textView.text = (NSString *)obj;
}

/**
 * 根据条件用来获取NSUIndex 对象，主要是根据条件进行数据遍历使用,会返回所有匹配的对象,使用- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))predicate
 */
- (void)select{
    NSArray *matchedArray = [self.itemArray bk_select:^BOOL(NSString *obj) {
        return obj.length > 5;
    }];
    NSLog(@"matchedArray = %@",matchedArray);
    
    self.textView.text = [matchedArray componentsJoinedByString:@"\n"];
}

/**
 * 根据条件用来获取NSUIndex 对象，主要是根据条件进行数据遍历使用,会返回所有不匹配的对象,使用- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))predicate
 */

- (void)reject{
    NSArray *matchedArray = [self.itemArray bk_reject:^BOOL(NSString *obj) {
        return obj.length > 7;
    }];
    NSLog(@"matchedArray = %@",matchedArray);
    self.textView.text = [matchedArray componentsJoinedByString:@"\n"];
}

/**
 * 对数组内部成员进行某种操作后并返回新的数组
 */
- (void)map{
    NSArray *newArray = [self.itemArray bk_map:^id(NSString *obj) {
        return [obj stringByAppendingString:@"hah"];
    }];
    NSLog(@"newArray = %@",newArray);
    self.textView.text = [newArray componentsJoinedByString:@"\n"];
}

/**
 * 对数组内部成员进行某种加的操作
 */
- (void)reduce{
    
    NSString *allFontString = [self.itemArray bk_reduce:@"" withBlock:^id(id sum, id obj) {
        return [sum stringByAppendingString:obj];
    }];
    self.textView.text = allFontString;
    NSLog(@"allFontString = %@",allFontString);
    self.textView.text = allFontString;
    
}

/**
 * 对数组内部成员进行 NSInteger 的操作,比如计算所有的商品个数,一般是使用 forin 遍历,把商品个数相加
 */
- (void)reduceInteger{
    
    NSInteger allLength = [self.itemArray bk_reduceInteger:0 withBlock:^NSInteger(NSInteger result, NSString *obj) {
        return result + obj.length;
    }];
    
    NSLog(@"all length = %ld",allLength);
    
    self.textView.text = [NSString stringWithFormat:@"all length = %ld",allLength];
}

/**
 * 对数组内部成员进行 CGFloat 的操作,比如计算用户的余额
 */
- (void)reduceFloat{
    NSArray *balances = @[@"100.98",@"876994.35",@"12446547658"];
    
    CGFloat allBalance = [balances bk_reduceFloat:0 withBlock:^CGFloat(CGFloat result, id obj) {
        return result + [obj floatValue];
    }];
    
    NSLog(@"allBalance =%.2f",allBalance);
    self.textView.text = [NSString stringWithFormat:@"allBalance =%.2f",allBalance];
}

/**
 * 根据某种条件对数组内部成员进行判断,检索是否满足该条件的对象存在
 */
- (void)any{
    
    BOOL exist = [self.itemArray bk_any:^BOOL(NSString *obj) {
        return [obj isEqualToString:@"Marion-Italic"];
    }];
    
    NSString *result = nil;
    
    if (exist) {
        result = @"Marion-Italic 存在";
    }else {
        result = @"Marion-Italic 不存在";
    }
    
    self.textView.text = result;
}

/**
 * 根据某种条件对数组内部成员进行判断,检索不满足该条件的对象是否存在
 */
- (void)none{
    BOOL exist = [self.itemArray bk_none:^BOOL(NSString *obj) {
        return obj.length > 100;
    }];
    
    self.textView.text = [NSString stringWithFormat:@"%d",exist];
}

/**
 * 判断数组内部成员是否都满足某一个条件
 */
- (void)all{
    BOOL allIn = [self.itemArray bk_all:^BOOL(id obj) {
        return [obj isKindOfClass:[NSString class]];
    }];
    
    self.textView.text = [NSString stringWithFormat:@"%d",allIn];
}
/**
 * 判断两个数组中元素的相关性,用于两个数组之间
 */
- (void)corresponds{
    BOOL allMatch = [self.itemArray bk_corresponds:[UIFont familyNames] withBlock:^BOOL(id obj1, id obj2) {
        return [obj1 isEqual:obj2];
    }];
    
    self.textView.text = [NSString stringWithFormat:@"%d",allMatch];
}

#pragma mark - <UITableViewDataSource>

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.methods.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }
    cell.textLabel.text = self.methods[indexPath.row];
    return cell;
}


#pragma mark - <UITableViewDelegate>

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    SEL selector = NSSelectorFromString(self.methods[indexPath.row]);
    IMP imp = [self methodForSelector:selector];
    void (*func)(id, SEL) = (void *)imp;
    func(self,selector);
}

#pragma mark - GET

- (NSArray *)itemArray{
    if (!_itemArray) {
        _itemArray = [UIFont familyNames];
    }
    return _itemArray;
}

- (UITextView *)textView{
    if (!_textView) {
        _textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width , 200)];
        _textView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
        _textView.textColor = [UIColor whiteColor];
    }
    return _textView;
}

- (UITableView *)tableView{
    if (!_tableView) {
        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, self.view.bounds.size.height - 200) style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        _tableView.rowHeight = 40;
    }
    return _tableView;
}

- (NSArray *)methods{
    if (!_methods) {
        _methods = @[@"each",
                     @"apply",
                     @"match",
                     @"select",
                     @"reject",
                     @"map",
                     @"reduce",
                     @"reduceInteger",
                     @"reduceFloat",
                     @"any",
                     @"none",
                     @"all",
                     @"corresponds"];
    }
    return _methods;
}

@end
